#pragma once
#include<iostream>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<cstring>
using namespace std;

const  std::string serverip = "0.0.0.0";
const int serverport = 8080;

class TcpServer
{
public:

    TcpServer(const std::string& ip = serverip, const uint16_t& serverport = serverport) :_ip(serverip), _port(serverport)
    {}

    ~TcpServer()
    {}


    bool Socket()
    {
        _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensockfd < 0)
        {
            cout << "socket failed" << endl;
            return false;
        }
        return true;
    }

    bool Bind()
    {
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = inet_addr(_ip.c_str());
        socklen_t len;
        int n = bind(_listensockfd, (struct sockaddr*)&local, len);
        if (n < 0)
        {
            cout << "bind failed" << endl;
            return false;
        }
        return true;
    }

    bool Listen(int backlog)
    {
        int n = listen(_listensockfd, backlog);
        if (n < 0)
        {
            cout << "listen failed" << endl;
            return false;
        }
        return true;
    }

    int Accpte()
    {
        struct sockaddr_in server;
        memset(&server, 0, sizeof(server));
        socklen_t len = sizeof(server);
        int fd = accept(_listensockfd, (struct sockaddr*)&server, &len);
        if (fd < 0)
        {
            cout << "accept failed" << endl;
            exit(3);
        }
        return fd;
    }

    int Connect(std::string& ip, uint16_t& port)
    {
        struct sockaddr_in server;
        socklen_t len = sizeof(server);
        server.sin_family = AF_INET;
        server.sin_port = htons(8080);
        server.sin_addr.s_addr = inet_addr("116.204.104.202");
        int fd = connect(_listensockfd, (struct sockaddr*)&server, len);
        if (fd < 0)
        {
            cout << "connect failed" << endl;
            return -1;
        }
        port = ntohs(server.sin_port);
        ip = inet_ntoa(server.sin_addr);
        return fd;
    }

    void Read(int socketfd, string& buffer)
    {
        char str[1024];
        ssize_t n = read(socketfd, str, sizeof(str));
        if (n < 0)
        {
            cout << "read failed" << endl;
            exit(1);
        }
        else if (n == 0)
        {
            cout << "client close,me too!" << endl;
            exit(0);
        }
        else
        {
            str[n] = 0;
        }

        buffer = str;

    }

    void Write(const std::string& str, int socketfd)
    {
        ssize_t n = write(socketfd, str.c_str(), str.size());
        if (n < 0)
        {
            std::cout << "write failed" << endl;
            exit(2);
        }
    }



private:
    int _listensockfd;
    std::string _ip;
    uint16_t _port;
};